package com.addplus.townmall.server.web.provider.serviceimpl.questionModule;

import com.addplus.townmall.server.api.constant.ErrorCode;
import com.addplus.townmall.server.api.exception.ErrorException;
import com.addplus.townmall.server.api.mapper.exam.KnowledgeMapper;
import com.addplus.townmall.server.api.mapper.exam.PaperMapper;
import com.addplus.townmall.server.api.mapper.exam.PaperQuestionMapper;
import com.addplus.townmall.server.api.mapper.exam.QuestionMapper;
import com.addplus.townmall.server.api.model.exam.*;
import com.addplus.townmall.server.api.service.web.questionModule.QuestionService;
import com.addplus.townmall.server.api.utils.DataUtils;
import com.addplus.townmall.server.web.provider.serviceimpl.paperModule.PaperServiceImpl;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.rpc.RpcContext;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service(interfaceClass = QuestionService.class)
public class QuestionServiceImpl implements QuestionService {
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private KnowledgeMapper knowledgeMapper;
    @Autowired
    private PaperQuestionMapper paperQuestionMapper;
    @Autowired
    private PaperMapper paperMapper;

    @Override
    public Boolean addQuestion(Question question) throws Exception {
        if(question==null||DataUtils.isEmpty(question.getContent(),question.getAnswer(),question.getQuestionType())){
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        String content=question.getContent();
//        if(content!=null&&content.startsWith("<p>")){
//            Document doc =Jsoup.parse(content);
//            question.setContent(doc.getElementsByTag("p").text());
//        }
        if(question.getQuestionType().equals("单选题")||question.getQuestionType().equals("多选题")){
            if(question.getChoiceNum()==null||question.getChoiceNum()==0){
                throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
            }
            if(DataUtils.isEmpty(question.getChoiceA(),question.getChoiceB(),question.getChoiceC(),question.getChoiceD())){
                throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
            }
            if(question.getChoiceNum()>4&&question.getChoiceE()!=null&&!question.getChoiceE().equals("")){
                throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
            }
            if(question.getChoiceNum()>5&&question.getChoiceF()!=null&&!question.getChoiceF().equals("")){
                throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
            }
            if(question.getChoiceNum()>6&&question.getChoiceG()!=null&&!question.getChoiceG().equals("")){
                throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
            }
            if(question.getChoiceNum()>7&&question.getChoiceH()!=null&&!question.getChoiceH().equals("")){
                throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
            }
        }
        question.setIsDeleted(0);
        question.setGmtCreate(new Date());
        question.setGmtModified(new Date());
        int count=questionMapper.insert(question);
        if(count<1){
            throw new ErrorException(ErrorCode.SYS_ERROR_DATABASEFAIL);
        }
        return true;
    }

    @Override
    public Boolean updateQuestion(Question question) throws Exception {
        if (question == null || DataUtils.EmptyOrNegative(question.getId())) {
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        String content=question.getContent();
//        if(content!=null&&content.startsWith("<p>")){
//            if(content.contains("<img")){
//                question.setPicture(getImgStr(content));
//            }
//            Document doc =Jsoup.parse(content);
//            question.setContent(doc.getElementsByTag("p").text());
//        }
        Question question1=questionMapper.selectById(question.getId());
        if(question1!=null){
            question.setGmtModified(new Date());
            String modifyUser= RpcContext.getContext().getAttachment("id");
            question.setContributor(modifyUser);
            int count = questionMapper.updateById(question);
            if(count>0){
                return true;
            }else{
                throw new ErrorException(ErrorCode.SYS_ERROR_DATABASEFAIL);
            }
        }else{
            throw new ErrorException(ErrorCode.SYS_ERROR_NOT_AVAILABLE);
        }
    }

    /**
     * 得到网页中图片的地址
     * @param htmlStr html字符串
     * @return List<String>
     */
    private  String getImgStr(String htmlStr) {
        StringBuilder pics = new StringBuilder();
        String img = "";
        Pattern p_image;
        Matcher m_image;
        String regEx_img = "<img.*src\\s*=\\s*(.*?)[^>]*?>";
        p_image = Pattern.compile(regEx_img, Pattern.CASE_INSENSITIVE);
        m_image = p_image.matcher(htmlStr);
        while (m_image.find()) {
            // 得到<img />数据
            img = m_image.group();
            pics.append(img+" ");
            // 匹配<img>中的src数据
//            Matcher m = Pattern.compile("src\\s*=\\s*\"?(.*?)(\"|>|\\s+)").matcher(img);
//            while (m.find()) {
//                pics.add(m.group(1));
//            }
        }
        return pics.toString();
    }
    @Override
    public IPage<QuestionExt> getAllQuestionByPage(String content,Integer pageNo, Integer pageSize,String questionType) throws Exception {
        if(DataUtils.EmptyOrNegativeOrZero(pageNo,pageSize)){
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        IPage<QuestionExt> page = new Page<QuestionExt>(pageNo,pageSize);
        List<QuestionExt> questionExtList=null;
        questionExtList=questionMapper.getAllQuestionByPage(page,content,questionType);
//        if(content!=null&&!"".equals(content)){
//
//        }else{
//            if(questionType.equals("单选题")||questionType.equals("多选题")||questionType.equals("判断题")||questionType.equals("填空题")||questionType.equals("解答题")||questionType.equals("编程题")){
//                questionExtList=questionMapper.getAllQuestionByType(page,questionType);
//            }else{
//                questionExtList=questionMapper.getAllQuestionByPage(page);
//            }
//        }


        if(questionExtList==null||questionExtList.isEmpty()){
            throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
        }
        for(QuestionExt question:questionExtList){
            String s=question.getContent();
//            if(question.getAnswer()!=null&&question.getAnswer().contains("\\n")){
//                question.setAnswer("<p>"+question.getAnswer().replace("\\n","<br/>")+"</p>");
//            }
//            System.out.println(question.getAnswer());
            if(s!=null&&!s.equals("")){
                if(s.startsWith("<p>")){
                    Document doc =Jsoup.parse(s);
                    question.setContentConplete(doc.getElementsByTag("p").text());
                    question.setContent(question.getContentConplete());
                }else {
                    question.setContentConplete(s);
                }
            }
//            Integer knowledgeId=question.getKnowledgeId();
//            if(knowledgeId!=null&&knowledgeId!=0){
//                Knowledge knowledge=knowledgeMapper.selectById(knowledgeId);
//                if(knowledge.getKnowledgeName()!=null&&!knowledge.getKnowledgeName().equals("")){
//                    question.setKnowledge(knowledge.getKnowledgeName());
//                }
//            }
        }
        page.setRecords(questionExtList);
        return page;
    }

    @Override
    public Question getQuestionById(Integer id) throws Exception {
        if(DataUtils.EmptyOrNegativeOrZero(id)){
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        Question question=questionMapper.selectById(id);
        if(question!=null){
            return question;
        }
        throw new ErrorException(ErrorCode.SYS_ERROR_NULLDATE);
    }

    @Override
    public Boolean deltetQuestion(Integer id) throws Exception {
        if(DataUtils.EmptyOrNegativeOrZero(id)){
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        Question question=new Question();
        question.setIsDeleted(1);
        question.setId(id);
        question.setGmtModified(new Date());
        int count=questionMapper.updateById(question);
        if(count<1){
            throw new ErrorException(ErrorCode.SYS_ERROR_DATABASEFAIL);
        }
        return true;
    }
    private static Integer index;
    private static Integer questionIndex;
    @Override
    public Map<String,Object> exportQuestionByIds(String describe,String idStr,String paperName) throws Exception {
        if(DataUtils.isEmpty(idStr,paperName)){
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        Paper paper=new Paper();
        Date date=new Date();
        paper.setIsDeleted(0);
        paper.setGmtCreate(date);
        paper.setGmtModified(date);
        paper.setModifyUser(Integer.valueOf(RpcContext.getContext().getAttachment("id")));
        paper.setPaperName(paperName);
        if(describe!=null&&!describe.equals("")&&!describe.equals("undefined")){
            paper.setPaperDescribe(describe);
        }
        paperMapper.insert(paper);
        List<String> idsList= Arrays.asList(idStr.split(","));
        List<Integer> idList = new ArrayList<Integer>();
        for (String x : idsList) {
            Integer z = Integer.parseInt(x);
            idList.add(z);
        }
        index=1;
        questionIndex=1;
        List<Question> questionList=questionMapper.selectQuestionsByIds(idList);
        Map<String,Object> dataMap=new HashMap<>();
        Map<String,List<Question>> map=questionList.stream().filter(o -> Objects.nonNull(o.getQuestionType())).collect(Collectors.groupingBy(Question::getQuestionType));
        List<Map<String,Object>> allQuestionList=new ArrayList<>();
        for(Map.Entry<String,List<Question>> entry:map.entrySet()){
            if(entry.getKey().equals("单选题")){
                allQuestionList.add(getQuestionList(entry.getValue(),"单选题",paper.getId(),idStr,date));
            }
            if(entry.getKey().equals("多选题")){
                allQuestionList.add(getQuestionList(entry.getValue(),"多选题",paper.getId(),idStr,date));
            }
            if(entry.getKey().equals("判断题")){
                allQuestionList.add(getQuestionList(entry.getValue(),"判断题",paper.getId(),idStr,date));
            }
            if(entry.getKey().equals("填空题")){
                allQuestionList.add(getQuestionList(entry.getValue(),"填空题",paper.getId(),idStr,date));
            }
            if(entry.getKey().equals("解答题")){
                allQuestionList.add(getQuestionList(entry.getValue(),"解答题",paper.getId(),idStr,date));
            }
            if(entry.getKey().equals("编程题")){
                allQuestionList.add(getQuestionList(entry.getValue(),"编程题",paper.getId(),idStr,date));
            }
        }
        dataMap.put("allQuestionList",allQuestionList);
        dataMap.put("paperName",paperName);
        dataMap.put("answerTitle",paperName+"答案及评分标准");

        return dataMap;
    }

    private Map<String,Object> getQuestionList(List<Question> questions,String questionType,Integer paperid,String idStr,Date date) {
        Map<String,Object> questionMap=new HashMap<>();
        questionMap.put("questionList", listToMap(questions));
        questionMap.put("questionTitle", PaperServiceImpl.intToChinese(index)+"、"+questionType);
        index++;
        questionMap.put("score",1);
        questionMap.put("typeTotalScore",questions.size());

        insertPaperQuestion(paperid,questions.size(),1,questionType,idStr.toString(),date);
        return questionMap;
    }

    private void insertPaperQuestion(Integer paperId,Integer questionNum,Integer score,String questionType,String questionIds,Date date){
        PaperQuestion paperQuestion=new PaperQuestion();
        paperQuestion.setIsDeleted(0);
        paperQuestion.setPaperId(paperId);
        paperQuestion.setQuestionNum(questionNum);
        paperQuestion.setQuestionType(questionType);
        paperQuestion.setScore(score);
        paperQuestion.setQuestionIds(questionIds);
        paperQuestion.setGmtCreate(date);
        paperQuestion.setGmtModified(date);
        paperQuestionMapper.insert(paperQuestion);
    }
    /**
     * List<Question>转为List<Map<String,Object>>
     * @param questions
     * @return
     */
    /**
     * List<Question>转为List<Map<String,Object>>
     * @param questions
     * @return
     */
    private static List<Map<String,Object>> listToMap(List<Question> questions){
        List<Map<String,Object>> mapList=new ArrayList<>();
        for(Question question:questions){
            Map<String,Object> map=new HashMap<>();
            map.put("content",questionIndex+". "+replaceSpecialCharacter(question.getContent()));
//            map.put("picture",question.getPicture());
            map.put("answer",questionIndex+". "+replaceSpecialCharacter(question.getAnswer()));
            map.put("questionType",question.getQuestionType());
            if(question.getQuestionType().equals("单选题")||question.getQuestionType().equals("多选题")){
                map.put("choiceA",replaceSpecialCharacter(question.getChoiceA()));
                map.put("choiceB",replaceSpecialCharacter(question.getChoiceB()));
                map.put("choiceC",replaceSpecialCharacter(question.getChoiceC()));
                map.put("choiceD",replaceSpecialCharacter(question.getChoiceD()));
                map.put("choiceE",replaceSpecialCharacter(question.getChoiceE()));
                map.put("choiceF",replaceSpecialCharacter(question.getChoiceF()));
                map.put("choiceG",replaceSpecialCharacter(question.getChoiceG()));
                map.put("choiceH",replaceSpecialCharacter(question.getChoiceH()));
            }
            mapList.add(map);
            questionIndex++;
        }
        return mapList;
    }

    /**
     * XML中的特殊字符替换成转义字符.
     */
    public static String replaceSpecialCharacter(String value) {
        if (value == null) {
            return null;
        }

        value = value.replaceAll("&", "&amp;");
        value = value.replaceAll("<", "&lt;");
        value = value.replaceAll(">", "&gt;");
        value = value.replaceAll("'", "&apos;");
        value = value.replaceAll("\"", "&quot;");
        value = value.replaceAll("\n", "<w:br />");
        return value;
    }

    @Override
    public List<QuestionExt> getQuestionByIds(String idsArr) throws Exception {
        if(DataUtils.isEmpty(idsArr)){
            throw new ErrorException(ErrorCode.SYS_ERROR_PARAM);
        }
        List<String> idsList= Arrays.asList(idsArr.split(","));
        List<Integer> idList = new ArrayList<Integer>();
        for (String x : idsList) {
            Integer z = Integer.parseInt(x);
            idList.add(z);
        }
        String[] questionTypeArr={"单选题","多选题","判断题","填空题","解答题","编程题"};
        index=1;
        questionIndex=1;
        List<Question> questionList=questionMapper.selectQuestionsByIds(idList);
        Map<String,List<Question>> map=questionList.stream().filter(o -> Objects.nonNull(o.getQuestionType())).collect(Collectors.groupingBy(Question::getQuestionType));
        List<QuestionExt> questionExtList=new ArrayList<>();
        for(Map.Entry<String,List<Question>> entry:map.entrySet()){
            for(int i=0;i<questionTypeArr.length;i++){
                if(entry.getKey().equals(questionTypeArr[i])){
                    QuestionExt questionExt=new QuestionExt();
                    questionExt.setQuestionList(entry.getValue());
                    questionExt.setQuestionTitle(PaperServiceImpl.intToChinese(index)+"、"+entry.getKey());
                    index++;
                    questionExt.setScore(1);
                    questionExt.setTypeTotalScore(entry.getValue().size());
                    questionExtList.add(questionExt);
                }
            }

        }
        return questionExtList;
    }
}
